#define SHORTMIN 444
#define SHORTMAX 1333
#define LONGMIN 1334
#define LONGMAX 2222

#define MIDDLE 1
#define START 0

volatile unsigned char dataAvailable = 0;
volatile unsigned int dataBuffer = 0;           //Circular Buffer To Store IR Data Words


volatile unsigned char edgeCount = 0;           //Counts The Number Of Transitions In A Transmission
volatile unsigned long previousEdgeTime = 0;    //Stores The Time Of The Previous Edge
volatile unsigned char prevLogicValue = 0;      //Record The Previous Logic Value
volatile unsigned int data = 0x00;              //Store IR Data Bits 
volatile signed char bitCount = 13;             //Current Data Bit Position

volatile unsigned long timeSinceLastEdge = 0;
volatile unsigned long spaceTime = 0;

volatile unsigned char periodPosition = 1;      // 1 = Middle, 0 = Start

void setup()
{
  Serial.begin(115200);
  Serial.println("Starting...");
  attachInterrupt(0, changeEventISR, CHANGE);         // Create An Change Triggered External Interrupt On Pin 2.
}

void loop()
{
  if(dataAvailable > 0)
  {
     Serial.println(dataBuffer, BIN);
     dataAvailable--;
  }  
  
}

void changeEventISR()
{ 
  //Start Of New Command
  if(bitCount == 13)
  {
    previousEdgeTime = micros();                       //Record Edge Time
    periodPosition = MIDDLE;                           //Update Period Position (Command Aways Starts In Middle)
    data = 0b0010000000000000;                         //Reset Data  
    bitCount = 12;
    prevLogicValue = 1;
    edgeCount= 1;                                      //Mark First Rising Edge     
  }
  //Edge In Mid Command
  else
  {
    unsigned long currentedgeTime = micros(); 
    timeSinceLastEdge = currentedgeTime - previousEdgeTime;            //Calculate Pulse Time
    previousEdgeTime = currentedgeTime;
                          
    edgeCount++;
    if(timeSinceLastEdge > LONGMIN && timeSinceLastEdge < LONGMAX)
    {
        Serial.println("Long Pulse");
       //Long Pulse
       if(periodPosition == MIDDLE)
       {
         //Data Pulse        
         prevLogicValue = 1 - prevLogicValue;          //Invert Logic Value 
         data = data & (prevLogicValue << bitCount);
         bitCount--;
         Serial.println(bitCount);
       }
       else
       {
         //ERROR Should Never Have a Long Pulse When In Start Position
         bitCount = 13;         
       }
    }
    else if(timeSinceLastEdge > SHORTMIN && timeSinceLastEdge < SHORTMAX)
    {
       Serial.println("short Pulse");
       //Short Pulse 
       if(periodPosition == MIDDLE)
       {
         //Non-Data Transmission
         periodPosition = START;
       }
       else
       {
         //Data Transmission         
         data = data & (prevLogicValue << bitCount);
         periodPosition = MIDDLE;
         bitCount--;
         Serial.println(bitCount);
       }
    }
    else
    {
       Serial.print("Invalid pulse width: ");
       Serial.print(timeSinceLastEdge);
       Serial.println(" uSec");
       
       //Error Invalid Pulse Width
        bitCount = 13;       
    }
  }
  
  if(bitCount < 0)
  {
    //Transmission Complete
    dataBuffer = data;             //Put New Data In Buffer
    dataAvailable++;               //Indicate More Data Is Available
    bitCount = 13;
    Serial.println("Complete Command");
  }
}
